﻿using Castle.Core.Internal;
using Castle.DynamicProxy;
using SqlSugar;
using SunnyPaine.Autofac.Extension.SqlSugar.Context;
using SunnyPaine.Autofac.Extension.SqlSugar.Entities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SunnyPaine.Autofac.Extension.SqlSugar.Interceptor
{
    /// <summary>
    /// 数据库数据连接拦截器。
    /// </summary>
    public class TransactionInterceptor : IInterceptor
    {
        private SqlSugarScope _scope;
        private string[] configIds;

        #region 构造方法
        /// <summary>
        /// 使用默认的参数创建 <see cref="TransactionInterceptor"/> 的实例。
        /// </summary>
        public TransactionInterceptor()
        { }
        #endregion


        #region 公共方法
        /// <summary>
        /// 使用指定的参数创建 <see cref="TransactionInterceptor"/> 的实例。
        /// </summary>
        /// <param name="scope">SqlSugar的所有数据连接实例。</param>
        /// <param name="infos">SqlSugar的所有数据连接配置。</param>
        public void Init(SqlSugarScope scope, List<ConnectionInfo> infos)
        {
            this._scope = scope;
            this.configIds = infos.Select(p => p.ConfigId).ToArray();
            this.GetConnection();
        }
        #endregion


        #region 公共方法，IInterceptor成员
        /// <summary>
        /// 拦截目标方法。
        /// </summary>
        /// <param name="invocation"></param>
        public void Intercept(IInvocation invocation)
        {
            string methodName = invocation.Method.Name;

            Console.WriteLine($"{methodName} 执行前");

            //判断方法是否有TransactionScope标记
            TransactionScopeAttribute attribute = invocation.MethodInvocationTarget.GetAttribute<TransactionScopeAttribute>();
            if (attribute != null && attribute.Enabled)
            {
                try
                {
                    this._scope.BeginTran();

                    //调用业务方法
                    invocation.Proceed();

                    //释放数据库连接
                    this._scope.CommitTran();
                }
                catch (Exception ex)
                {
                    this._scope.RollbackTran();
                    throw ex;
                }
                finally
                {
                    this.CloseConnection();
                }
            }
            else
            {
                //调用业务方法
                invocation.Proceed();
            }

            Console.WriteLine($"{methodName} 执行完毕");
        }
        #endregion


        #region 私有方法
        /// <summary>
        /// 装载数据库连接的数据上下文。
        /// </summary>
        private void GetConnection()
        {
            IDictionary<string, ISqlSugarClient> dict = new Dictionary<string, ISqlSugarClient>();
            foreach (string configId in this.configIds)
            {
                dict.Add(configId, this._scope.GetConnection(configId));
            }
            DBAContext.SetClient(dict);
        }

        /// <summary>
        /// 关闭清理数据库连接的数据上下文。
        /// </summary>
        private void CloseConnection()
        {
            DBAContext.Clear();
        }
        #endregion
    }
}
